package com.greatwall.hip.cms.model;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.io.Serializable;
import java.util.Optional;

/**
 * 响应信息主体
 *
 * @param <T> 泛型标记
 * @author ljl
 */
@ApiModel(description = "返回信息")
@Data
public class Result<T> implements Serializable {
    private static final long serialVersionUID = -1160662278280275915L;

    @ApiModelProperty(value = "code值", required = true)
    protected int code;

    @ApiModelProperty(value = "是否成功", required = true)
    protected boolean success;

    @ApiModelProperty(value = "消息", required = true)
    protected String msg;

    @ApiModelProperty("返回对象")
    protected T data;

    public Result(IResultCode resultCode) {
        this(resultCode, resultCode.getMsg(), null);
    }

    public Result(IResultCode resultCode, String msg) {
        this(resultCode, msg, null);
    }

    public Result(IResultCode resultCode, T data) {
        this(resultCode, resultCode.getMsg(), data);
    }

    public Result(IResultCode resultCode, String msg, T data) {
        this.code = resultCode.getCode();
        this.msg = msg;
        this.data = data;
        this.success = SystemCode.SUCCESS == resultCode;
    }

    /**
     * 判断返回是否为成功
     *
     * @param result Result
     * @return 是否成功
     */
    public static boolean isSuccess(Result<?> result) {
        return Optional.ofNullable(result)
                .map(r -> r.code)
                .map(code -> SystemCode.SUCCESS.code == code)
                .orElse(Boolean.FALSE);
    }

    /**
     * 判断返回是否为成功
     *
     * @param result Result
     * @return 是否成功
     */
    public static boolean isFail(Result<?> result) {
        return !Result.isSuccess(result);
    }

    /**
     * 获取data
     *
     * @param result Result
     * @param <T>    泛型标记
     * @return 泛型对象
     */
    public static <T> T getData(Result<T> result) {
        return Optional.ofNullable(result)
                .filter(r -> r.success)
                .map(x -> x.data)
                .orElse(null);
    }

    /**
     * 返回成功
     *
     * @param <T> 泛型标记
     * @return Result
     */
    public static <T> Result<T> success() {
        return new Result<>(SystemCode.SUCCESS);
    }

    /**
     * 成功-携带数据
     *
     * @param data 数据
     * @param <T>  泛型标记
     * @return Result
     */
    public static <T> Result<T> success(T data) {
        return new Result<>(SystemCode.SUCCESS, data);
    }

    /**
     * 根据状态返回成功或者失败
     *
     * @param status 状态
     * @param msg    异常msg
     * @param <T>    泛型标记
     * @return Result
     */
    public static <T> Result<T> status(boolean status, String msg) {
        return status ? Result.success() : Result.fail(msg);
    }

    /**
     * 根据状态返回成功或者失败
     *
     * @param status 状态
     * @param sCode  异常code码
     * @param <T>    泛型标记
     * @return Result
     */
    public static <T> Result<T> status(boolean status, IResultCode sCode) {
        return status ? Result.success() : Result.fail(sCode);
    }

    /**
     * 返回失败信息，用于 web
     *
     * @param msg 失败信息
     * @param <T> 泛型标记
     * @return {Result}
     */
    public static <T> Result<T> fail(String msg) {
        return new Result<>(SystemCode.FAILURE, msg);
    }

    /**
     * 返回失败信息
     *
     * @param rCode 异常枚举
     * @param <T>   泛型标记
     * @return {Result}
     */
    public static <T> Result<T> fail(IResultCode rCode) {
        return new Result<>(rCode);
    }

    /**
     * 返回失败信息
     *
     * @param rCode 异常枚举
     * @param msg   失败信息
     * @param <T>   泛型标记
     * @return {Result}
     */
    public static <T> Result<T> fail(IResultCode rCode, String msg) {
        return new Result<>(rCode, msg);
    }


}
